package com.duguo.dynamicmvc.factory.processor.controller;

import java.util.HashMap;
import java.util.Map;

import javassist.ClassPool;
import javassist.CtClass;
import javassist.CtMethod;

import com.duguo.dynamicmvc.factory.ControllerBuilder;
import com.duguo.dynamicmvc.factory.utils.BeanUtils;
import com.duguo.dynamicmvc.factory.utils.javassist.FieldUtils;
import com.duguo.dynamicmvc.factory.utils.javassist.MethodUtils;


public class ControllerMultiActionCreatorImpl implements ControllerMultiActionCreator{

	ControllerMethodCreator _controllerMethodCreator;
	ControllerClassCreator _controllerClassCreator;
	ControllerNameBuilder _controllerNameBuilder;
	ControllerInjectionCreator _controllerInjectionCreator;

    public Object createGeneralMultiActionController(Object parentController,String controllerName, ControllerBuilder controllerBuilder) throws Exception {
        Class multiActionControllerClass = getMultiActionControllerClass(parentController,controllerName,controllerBuilder);
        Object multiActionController = multiActionControllerClass.newInstance();
        BeanUtils.setFieldValue(multiActionController, "registedControllers", new HashMap<String, Object>());
        
        _controllerInjectionCreator.injectionFeilds(multiActionController);
        BeanUtils.setFieldValue(multiActionController, "controllerBuilder", controllerBuilder);
        return multiActionController;
    }


    public Class getStaticControllerClass(Object parentController, String controllerName, ControllerBuilder controllerBuilder) throws Exception {

        CtClass parentControllerCtClass = ClassPool.getDefault().get(parentController.getClass().getName());
        CtMethod tempCtMethod = MethodUtils.findMethod(parentControllerCtClass, "handleRequest");
		CtClass staticModelCtClass=controllerBuilder.getProcessorHolder().getModelProcessor().getStaticModelCtClass(parentControllerCtClass.getName());
        Class staticClass = _controllerMethodCreator.getStaticControllerClass(tempCtMethod,staticModelCtClass,parentControllerCtClass,controllerName,controllerBuilder,_controllerClassCreator);
        return staticClass;
    }

	Class getMultiActionControllerClass(Object parentController,String controllerName, ControllerBuilder controllerBuilder) throws Exception {
        CtMethod controllerHandlerCtMethod = _controllerMethodCreator.getHanderCtMethodFromParent(parentController.getClass().getName());
        String targetClassName = _controllerNameBuilder.getControllerInternalClassName(parentController.getClass().getName(),controllerName, true);
        createGeneralMultiActionControllerCtClass(controllerHandlerCtMethod, targetClassName,controllerBuilder);
        return ClassPool.getDefault().getClassLoader().loadClass(targetClassName);
    }


    private void createGeneralMultiActionControllerCtClass(CtMethod controllerHandlerCtMethod, String targetClassName, ControllerBuilder controllerBuilder) throws Exception{
        CtClass controllerCtClass = ClassPool.getDefault().makeClass(targetClassName);
        CtClass controllerInternalInterface=_controllerMethodCreator.getInternalInterface(controllerHandlerCtMethod);
        controllerCtClass.addInterface(controllerInternalInterface);
        setupMultiActionControllerCtClass(controllerCtClass, controllerHandlerCtMethod, false,null, controllerInternalInterface, false,controllerBuilder);
        _controllerInjectionCreator.setupInjectionFeilds(controllerCtClass);
        
        controllerCtClass.toClass();
    }


   

    public void setupMultiActionControllerCtClass(CtClass controllerCtClass, CtMethod controllerHandlerCtMethod, boolean hasDynamicController,Map<String,Object> viewMappings, CtClass controllerInternalInterface, boolean isSingleAction, ControllerBuilder controllerBuilder) throws Exception{
        if(isSingleAction) {
        	FieldUtils.setupField(controllerCtClass, controllerInternalInterface, "controller");
        }else{
            CtClass controllerBuilderCtClass = ClassPool.getDefault().get(ControllerBuilder.class.getName());
            FieldUtils.setupField(controllerCtClass, controllerBuilderCtClass, "controllerBuilder");
            
	    	FieldUtils.setupField(controllerCtClass, ClassPool.getDefault().get(Map.class.getName()), "registedControllers");
	    	_controllerMethodCreator.createControllerRegisterMethod(controllerCtClass);
	    	_controllerMethodCreator.createViewRegisterMethod(controllerCtClass);
        }
        _controllerMethodCreator.createMultiActionHandlerMethod(
                controllerCtClass,
                controllerInternalInterface,
                controllerHandlerCtMethod,
                hasDynamicController,viewMappings, isSingleAction,controllerBuilder);
    }

	public void setupDynamicControllerParentHandler(CtClass controllerCtClass, CtClass parentInternalInterfaceCtClass, CtMethod parentHandlerCtMethod, ControllerProcessor controllerProcessor) throws Exception{
		controllerCtClass.addInterface(parentInternalInterfaceCtClass);
		_controllerMethodCreator.createDynamicHandlerMethod(controllerCtClass,parentHandlerCtMethod, controllerProcessor);
	}


	public ControllerMethodCreator getControllerMethodCreator() {
		return _controllerMethodCreator;
	}


	public void setControllerMethodCreator(
			ControllerMethodCreator controllerMethodCreator) {
		_controllerMethodCreator = controllerMethodCreator;
	}


	public ControllerClassCreator getControllerClassCreator() {
		return _controllerClassCreator;
	}


	public void setControllerClassCreator(
			ControllerClassCreator controllerClassCreator) {
		_controllerClassCreator = controllerClassCreator;
	}


	public ControllerNameBuilder getControllerNameBuilder() {
		return _controllerNameBuilder;
	}


	public void setControllerNameBuilder(ControllerNameBuilder controllerNameBuilder) {
		_controllerNameBuilder = controllerNameBuilder;
	}


	public ControllerInjectionCreator getControllerInjectionCreator() {
		return _controllerInjectionCreator;
	}


	public void setControllerInjectionCreator(
			ControllerInjectionCreator controllerInjectionCreator) {
		_controllerInjectionCreator = controllerInjectionCreator;
	}

}
